#include <stdio.h>

#include "World.h"

#include "../Graphic/Graphic.h"
#include "../Log/Log.h"

sWorld ***World;

int World_Width = 128; // Wird Automatisch vergrößert
int World_Height = 32;
int World_Layer = 2;
int World_Version = 126;
char World_Background = 0;
char *World_File = "p1w";
int World_Locked;

void World_Create() {
    int X,Y;

    sWorld wSize;

    World_Locked = 1;
    /* Karte erstellen */
    World = malloc( World_Width * sizeof(wSize));
    for(X = 0; X < World_Width; X++)
        World[X] = malloc( World_Height * sizeof(wSize));
    for(X = 0; X < World_Width; X++)
        for(Y = 0; Y < World_Height; Y++)
            World[X][Y] = malloc( World_Layer * sizeof(wSize));
    /* Camera grenzen setzen */
    Graphic_SetCamera( World_Width*32, World_Height*32);
}

void World_Delete() {
    int X,Y;
    World_Locked = 1;
    /* Karte löschen */
    for(X = 0; X < World_Width; X++)
        for(Y = 0; Y < World_Height; Y++)
            free( World[X][Y] );
    for(X = 0; X < World_Width; X++)
        free( World[X] );
    free(World);
}

void World_Init() {
    int X,Y,Z;

    /* Karte erstellen */
    World_Create();

    /* Alles auf Null setzten */
    for(X = 0; X < World_Width; X++)
        for(Y = 0; Y < World_Height; Y++)
            for(Z = 0; Z < World_Layer; Z++) {
                World[X][Y][Z].Collision = 0;
                World[X][Y][Z].Tile = 0;
                /*if( Y > World_Height/2 && Z == 1)
                    World[X][Y][Z].Tile = 14;*/
        }
    World_Locked = 0;
    logDebug("World wurde erstellt %dbyte ", sizeof(World));
}

/** Save and Load **/

void World_Save( int Index) {
    char sFile[128];

    /* datei anlegen */
    sprintf (sFile, "Save%d.%s", Index, World_File);
    /* Speichern */
    World_SaveFile(sFile);
}

void World_SaveFile(char *sFile) {
    int X,Y,Z;
    FILE *fSave;
    sWorld wSize;

    fSave = fopen(sFile,"wb");
    if(fSave == NULL) {
        logError("Konnte die Welt nicht speichern! Welt %s", sFile);
        return;
    }

    /* Anfag der Datei */
    fseek(fSave,0,SEEK_SET);

    /* Version speichern */
    fwrite (&World_Version, sizeof(int), 1, fSave);

    /* Size speichern */
    fwrite (&World_Height, sizeof(int), 1, fSave);
    fwrite (&World_Width, sizeof(int), 1, fSave);
    fwrite (&World_Layer, sizeof(int), 1, fSave);

    fwrite (&World_Background, sizeof(char), 1, fSave);

    /* Layerweiße abspeichern */
    for(Z = 0; Z < World_Layer; Z++) {
        for(X = 0; X < World_Width; X++)
            for(Y = 0; Y < World_Height; Y++) {
                    fwrite (&World[X][Y][Z], sizeof (wSize), 1, fSave);

        }
    }

    /* Schließen */
    fclose(fSave);

    logDebug("Welt gespeichert");
}


void World_Load(int Index) {
    char sFile[128];

    /* datei anlegen */
    sprintf (sFile, "Save%d.%s", Index, World_File);
    /* Lade datei */
    World_LoadFile(sFile);
}

void World_LoadFile( char *sFile) {
    int X,Y,Z, Version;
    FILE *fSave;
    sWorld wSize;

    fSave = fopen(sFile,"rb");
    if(fSave == NULL) {
        logError("Konnte die Welt nicht laden! %s", sFile);
        return;
    }

    /* Anfag der Datei */
    fseek(fSave,0,SEEK_SET);

    /* Version check */
    fread(&Version, sizeof(int), 1, fSave);
    if(World_Version != Version) {
        logWarning("Alte Datei! Kann nicht geladen werden! Weltversion %d", Version);
        fclose(fSave);
        return;
    }

    /* Karte löschen */
    World_Delete();

    /* Größe auslesen */
    fread (&World_Height, sizeof(int), 1, fSave);
    fread (&World_Width, sizeof(int), 1, fSave);
    fread (&World_Layer, sizeof(int), 1, fSave);

    /* World einzelheiten */
    fread (&World_Background, sizeof(char), 1, fSave);

    //logDebug("%d %d", World_Height, World_Width);

    /* Neue erstellen */
    World_Create();

    /* Map lesen */
    for(Z = 0; Z < World_Layer; Z++) {
        for(X = 0; X < World_Width; X++)
            for(Y = 0; Y < World_Height; Y++) {
                    //fprintf(fSave,"%d|%d|\n", World[X][Y][Z].Tile, World[X][Y][Z].Collision);
                    fread  (&World[X][Y][Z], sizeof (wSize), 1, fSave);
        }
    }

    fclose(fSave);
    /* Welt wieder freigeben */
    World_Locked = 0;

    /* Naricht ausgeben */
    logDebug("Welt wurde erfolgreich geladen. H\x94he %d Breite %d", World_Height, World_Width);
}

/** Graphic **/

void World_Graphic() {
    int X,Y,Z,i;
    /* zeichnen wenn die welt verfügbar ist */
    if(World_Locked)
        return;
    /* Welt Zeichnen*/
    for(i = 1; i < Graphic_Tile; i++) {
        Graphic_LoadTile(i);
        for(X = 0; X < World_Width; X++)
            for(Y = 0; Y < World_Height; Y++)
                for(Z = 0; Z < World_Layer; Z++) {
                    if((int)World[X][Y][Z].Tile == i)
                        Graphic_Draw( X*32, Y*32, Z, false);
                }
    }
    /* Background zeichnen */
    Graphic_Background(World_Background);
}

/** Tile **/

void World_SetTile(int X, int Y, int iLayer, int Tile) {
    int iX, iY;

    /* nur wenn freigegeben */
    if(World_Locked)
        return;
    /* Nicht über die Karte */
    if( X < 0 || Y < 0 || iLayer < 0 || X/32 >= World_Width || Y/32 >= World_Height)
        return;

    iX = X/32;
    iY = Y/32;

    World[iX][iY][iLayer].Tile = Tile;
}

int World_GetTile( int X, int Y, int iLayer) {
    int iX, iY;

    /* nur wenn freigegeben */
    if(World_Locked)
        return;
    /* Nicht über die Karte */
    if( X < 0 || Y < 0 || iLayer < 0 || X/32 >= World_Width || Y/32 >= World_Height)
        return -1;

    iX = X/32;
    iY = Y/32;

    return World[iX][iY][iLayer].Tile;
}


